/* 

==========================================================

DX490a - Summer 2010

Instructor: Stelios Manousakis

==========================================================

Class 2.2:

Interfacing 1: Standard Computer Peripherals

Contents:

• Mouse

- in the server

- in the language

• Keyboard

- in the server

- in the language

==========================================================

*/



// ====== MOUSE ====== 

// A simple mouse has three different controls: X position, Y position, and a button. These are implemented in SuperCollider as control-rate UGens, therefore one can use them inside a SynthDef. 


// ------ Mouse in the server  ------


// ------ MouseX ------


{ SinOsc.ar(MouseX.kr(40, 10000, 1), 0, 0.1) }.play; // with exponential mapping



// ------ MouseY ------


{ SinOsc.ar(MouseY.kr(10000, 40, 1, 1), 0, 0.1) }.play; // with exponential mapping and lag



// ------ MouseButton ------


{ SinOsc.ar(MouseButton.kr(400, 440, 0.1), 0, 0.1) }.play;



// ------ Examples ------


/* Mouse-theremin from here:

Document.open("examples/demonstrations/Theremin.scd")

*/

(

play(

{

var f;

f = MouseY.kr(4000, 200, 'exponential', 0.8);

SinOsc.ar(

freq: f+ (f*SinOsc.ar(7,0,0.02)),

mul: MouseX.kr(0, 0.9)

)

}

)

)



/* Josh's record scratcher from here:

Document.open("/Applications/SuperCollider/examples/pieces/Record Scratcher.scd")

// move mouse to scrub the record.

// press mouse button to 'stop the record', you can scrub while it is stopped.

*/

(

s.boot;


SynthDef(\scratch, {arg gate = 1, buffer;

var buf, speed, env;

env = EnvGen.kr(

Env([0,1,0], [0.1, 0.1], \sin, 1),

gate, doneAction: 20);

speed = MouseX.kr(-10, 10);

speed = speed - DelayN.kr(speed, 0.1, 0.1);

speed = MouseButton.kr(1, 0, 0.3) + speed ;

buf = PlayBuf.ar(1, buffer, speed * BufRateScale.kr(buffer), loop: 1);

Out.ar(0, (buf * env).dup );

}).load(s);


a = Buffer.read(s, "sounds/a11wlk01.wav");

b = Synth(\scratch, [\buffer, a]);

)


b.set(\gate, 0); a.free;



// ------ Mouse in the language  ------

// To get mouse vaues in the language you'll need to use one of the Server-to-language tools mentioned in the Class2.1 example:


{SendReply.kr(Impulse.kr(5), \mouse, [MouseX.kr, MouseY.kr, MouseButton.kr.round], 2323)}.play;


r = OSCresponder(nil, 'mouse', { |t, r, msg| "mouse-stuff".postln; msg.postln }).add;


r.remove; // don't forget to .remove!



// You could also use the GetMouse class (GetMouseX and GetMouseY), which is part of the Republic quark. This is an sclang side version, so it doesn't need the server to be on.

// Install it if you don't have it:

Quarks.install( "Republic", checkoutIfNeeded: false)




// ====== KEYBOARD ====== 


// ------ Keystrokes in the server ------

// In a similar manner as with the mouse, there is a control-rate UGen for keystrokes, KeyState. It checks for keycode values


{ SinOsc.ar(800, 0, KeyState.kr(38, 0, 0.1)) }.play; // press 'j' (ATT: does not prevent typing!)



// ------ Keystrokes in the language ------

// In the language, there is a method for in SCView (the abstract Class of all GUIs) and Document that does something similar, called .keyDownAction, and there is also a .keyUpAction


// an example with a GUI window: this will only work if you the window is focused, which is useful, as it prevents typing:

(

w = SCWindow.new("key-tester");

w.view.keyDownAction = { arg view, char, modifiers, unicode, keycode;

[char, modifiers, unicode, keycode].postln;

};

w.front

)


// And a cool example from Josh Parmenter with Document (no typing prevention):

(

d = Document.current;


d.keyDownAction_({arg ...args; //"..." puts everything into an array

(args[1]==$c).if({

args[0].background_(Color.rand);

});

args.postln;

});

)

// now, type 'c'

Document.current.keyDownAction=nil // stop it

d.background_(Color.white); // back to the standard color



// You can have a look at this example too if you want: [modifiers]


// Here is a site where you can find a table with the keycode values of your keyboard

"open http://www.asciitable.com/".unixCmd